package cn.nju.seg.atg.GA;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import cn.nju.seg.atg.model.SimpleCFGNode;
import cn.nju.seg.atg.parse.Builder;
import cn.nju.seg.atg.util.CFGPath;
import cn.nju.seg.atg.util.PathUtil;

public class GA_for_ATG extends StringGA{
	/**
	 *  输入变量的二进制表示位数
	 */
	public static int len;        //          >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>可以改变，但必须 >=4,最好是偶数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<   
	
	/** 
	 * 目标函数参数的潜在解域的边界
	 */
	public static double LEFT_BOUNDARY = Math.pow(2, -510);
	public static double RIGHT_BOUNDARY = Math.pow(2, -500);
	
	/**
	 * 参与编码的变量总数，包括输入变量和辅助变量
	 */
	private static int numOfParamsAndAuxiVars;
	
	/**
	 * 当变量涉及浮点类型时，其二进制表示小数点左右两边的位数 
	 */
	private static int leftSideLen,rightSideLen;
	
	/**
	 *  (Li,Ri)的二进制表示长度，计算能源函数时用到 
	 */
	private static int length;       // 二进制表示数组长度
	
	
	/**
	 *  (Li,Ri)的二进制表示小数点左右两边的长度，计算能源函数时用到 
	 */
	private static int leftSideLength ,rightSideLength;
	
	/**
	 *  参数类型指标
	 */
	public static boolean isIntType = false;     //        >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>可以改变<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
	
	/**
	 *  对变量所做的限制,集合中的变量必须是正数
	 */
	private static Set<Integer> positiveSet;
	
	/**
	 *  对变量所做的限制,集合中的变量必须是负数
	 */
	private static Set<Integer> negativeSet;
	
	/**
	 *  对变量所做的限制,集合中的变量必须是非负
	 */
	private static Set<Integer> unNegativeSet;
	
	/**
	 * 对变量所做的限制,集合中的变量必须是非正
	 */
	private static Set<Integer> unPositiveSet;
	
	/**
	 *  对变量所做的限制，集合中的变量必须非0
	 */
	private static Set<Integer> unZeroSet;
	
	/**
	 *  必须是整型的变量集合，（针对混合型行参）
	 */
	private static Set<Integer> intSet;
	
	/**
	 *  已经计算过能源函数值的节点集合（用于辨别有不同能源函数值的for结点）
	 */
	private static List<String> finishCalNodeSet;
	
	/**
	 *  路径经过的节点名集合
	 */
	private static List<String> nodeSetInPath;
	
	/**
	 *  路径节点的能源函数值集合
	 */
	private static List<Double> nodeEnergyValueSetInPath;
	
	/* 当函数行参为整数类型时，模拟退火所用到的变量如下定义       */
	
	/**
	 * 整型行参的值
	 */
	private static List<Long> inputValue;
	
	/**
	 * 整型辅助变量的值
	 */
	private static List<Long> auxilaryValue;
	
	/* 当函数行参为浮点类型或混合类型（既有整数类型，又有浮点类型）时，模拟退火所用到的变量如下定义       */
	
	/**
	 * 浮点型或混合型行参的值
	 */
	private static List<Double> inputValue2;
	
	/**
	 * 浮点型辅助变量的值
	 */
	private static List<Double> auxilaryValue2;
	
	/**
	 * 具有最优适应度的个体对应的输入变量（针对整型行参）
	 */
	public static List<Long> mInputValue;
	
	/**
	 * 具有最优适应度的个体对应的输入变量（针对浮点型或混合型行参）
	 */
	public static List<Double> mInputValue2;
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	/**
	 * 类c
	 * 为callFunction中的函数调用做准备
	 */
//	@SuppressWarnings("rawtypes")
//	private static Class c = null;
	/**
	 * 为callFunction中的函数调用做准备
	 */
//	private static CallCPP callCPP = null;

	/**
	 * CallCPP中需要执行的函数名
	 */
//	private static String callFunctionName;
	
    private static String pathFile;
	
	/**
	 * 目标函数的参数个数
	 */
	public static int NUM_OF_PARAM;
	
	private static int numOfAuxiliaryVars;
	
	public GA_for_ATG(){
		super(len * numOfParamsAndAuxiVars,//染色体长度(包括所有输入变量和当前路径谓词需要的辅助变量）
			  4 * NUM_OF_PARAM * Builder.targetPath.getNumOfPathPredicates()+1,//个体总数:4nM+1
			  0.7,//交叉概率
			  10,//随机选择概率
			  50,//最大迭代次数
			  0,//初始种群中经预筛选的个体数目
			  2,//筛选个体时的最大迭代次数
			  0.1,//变异概率
			  0,//个体串中小数点位置
			  CrossoverModel.ctRoulette,//交叉方式
			  true);//数据统计
	}

	/**
	 * 获取每个个体的适应度值
	 */
	@Override
	protected double getFitness(int iChromIndex) {
		//计算一次适应度，试验次数加一次
		Builder.GA_trials ++;
		if(isIntType == true)  // 行参类型为 整型
		{ 
			inputValue = new ArrayList<Long>();
			auxilaryValue = new ArrayList<Long>();
			for (int i=0; i<numOfParamsAndAuxiVars; i++){
				if(i == 0)
				inputValue.add(new Long((long) (-15 + ((30)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));
				if(i == 1){
			        inputValue.add(new Long((long) (LEFT_BOUNDARY + ((RIGHT_BOUNDARY - LEFT_BOUNDARY)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));				 
				}
				else{
					auxilaryValue.add(new Long((long) (-15+ ((30)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));
				}				
			}
			return -generateTestDataForInt(Builder.targetPath);
		}
		else  // 行参类型为浮点型或混合型
		{
			inputValue2 = new ArrayList<Double>();
			auxilaryValue2 = new ArrayList<Double>();
//			System.out.println();
			for (int i=0; i<numOfParamsAndAuxiVars; i++){
				if(i == 0)
				inputValue2.add(new Double( (-15 + ((30)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));
				if(i == 1){
			        inputValue2.add(new Double((LEFT_BOUNDARY + ((RIGHT_BOUNDARY - LEFT_BOUNDARY)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));				 
				}
				else{
					auxilaryValue2.add(new Double((-15+ ((30)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(iChromIndex).getGenesAsStr())[i])));
				}				
			}
			return -generateTestDataForOther(Builder.targetPath);
		}
	}
	
    /**
     * 为种群初始化，即为每个个体初始基因序列
     */
	@Override
	protected void initPopulation() {
		initialConstraintSet();  // 初始化参数限制集
		Random rd = new Random();
		for (int i = 0; i < populationDim; i++){
            for (int iGene = 0; iGene < chromosomeDim; iGene++){   	
                ((CharsChromosome) this.chromosomes[i]).genes[iGene] = getRandomGeneFromPossGenes();
            }
            for(int j = 0;j < numOfAuxiliaryVars;j++){
            	double tempValue = (LEFT_BOUNDARY + ((RIGHT_BOUNDARY - LEFT_BOUNDARY)/(Math.pow(2.0,len)))*getChromValAsArray(this.getChromosome(i).getGenesAsStr())[j+NUM_OF_PARAM]);
                Integer in = new Integer(j+1+NUM_OF_PARAM);
                if(tempValue == 0 && ( unZeroSet.contains(in) ||
			        positiveSet.contains(in) ||
			        negativeSet.contains(in))){
                	int alterBit = rd.nextInt(len);
    				while(alterBit == 0)
    				{
    					alterBit = rd.nextInt(len);
    				}
    				((CharsChromosome) this.chromosomes[i]).genes[len*(NUM_OF_PARAM+j)+alterBit] = '1';
                }
                if(positiveSet.contains(in) || unNegativeSet.contains(in)){
                	;//do nothing
                }
                else if(negativeSet.contains(in) || unPositiveSet.contains(in)){
                	((CharsChromosome) this.chromosomes[i]).genes[len*(NUM_OF_PARAM+j)] = '1';
    			}
            }
		}
	}
	
	/**
	 * ATG核心过程
	 * @param pathIndex
	 * @return
	 * @throws GAException 
	 */
	public static int generateTestData(int pathIndex)
	{
/*		try {
			c = Class.forName("cn.nju.seg.atg.callCPP.CallCPP");
			callCPP = (CallCPP)c.newInstance();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		callFunctionName = "call" + (Builder.funcName.charAt(0)+"").toUpperCase() + Builder.funcName.substring(1, Builder.funcName.indexOf("("));
*/		
		pathFile = "/home/zy/atg_data/" + Builder.funcName.substring(0, Builder.funcName.indexOf("(")) + ".dat";		
		
		/*  覆盖路径指标，-1表示未覆盖测试路径    */
		int isCovered = -1;  
		// 初始化长度
		initialLens();             
		numOfAuxiliaryVars = 15;
//		numOfParamsAndAuxiVars = NUM_OF_PARAM + Builder.targetPath.getNumOfAuxiliaryVars();
		numOfParamsAndAuxiVars = NUM_OF_PARAM + numOfAuxiliaryVars;
		Builder.optimalParams = new double[NUM_OF_PARAM];
		
		GA_for_ATG GAforATG = new GA_for_ATG();
		GAforATG.run();
		
		if(isIntType == true){
			for(int i=0;i<NUM_OF_PARAM;i++){
				Builder.optimalParams[i] = mInputValue.get(i).shortValue();
			}
		}
		else{
			for(int i=0;i<NUM_OF_PARAM;i++){
				Builder.optimalParams[i] = mInputValue2.get(i).doubleValue();
			}
		}
		
		//初始化覆盖到的最长路径片段为空
		CFGPath maxPath = new CFGPath();
		//执行程序
		callFunction();
		//读取路径
		List<CFGPath> excutedPaths1 = PathUtil.readPath(pathFile);
		//计算当前时刻目标路径被覆盖到的部分路径中最长的一条
		CFGPath coveredPath1 = getCoveredPath(excutedPaths1, Builder.targetPath);		
		//更新目标路径能被覆盖到的最长部分路径
		maxPath.update(coveredPath1);
				
		//判断是否已覆盖目标路径
		boolean isCoveredTargetPath = maxPath.isTargetPath(Builder.targetPath);
		     
		//返回结果
		if (isCoveredTargetPath)
		{
			Builder.allPaths.get(pathIndex).setCovered(true);
		    Builder.allPaths.get(pathIndex).setOptimalParams(maxPath.getOptimalParams());
			Builder.allPaths.get(pathIndex).setNumOfCoveredNodes(maxPath.getPath().size());
			Builder.allPaths.get(pathIndex).setEndCoveredNodeName(maxPath.getEndNodeName());
					
			isCovered = (pathIndex + 1);
		}
		else
		{ 			
			Builder.allPaths.get(pathIndex).setCovered(false);
			if (Builder.allPaths.get(pathIndex).getNumOfCoveredNodes() < maxPath.getPath().size())
			{
				Builder.allPaths.get(pathIndex).setOptimalParams(maxPath.getOptimalParams());
				Builder.allPaths.get(pathIndex).setNumOfCoveredNodes(maxPath.getPath().size());
				Builder.allPaths.get(pathIndex).setEndCoveredNodeName(maxPath.getEndNodeName());
			}

		    isCovered = -1;
		}
		return isCovered;
    }
	
	/**
	 * 执行待测试函数
	 */
//	@SuppressWarnings({ "unchecked" })
	private static void callFunction()
	{
		//开始计时
		Builder.function_time = Builder.function_time - System.currentTimeMillis();
		
//		Builder.callCPP.callCheckX(Builder.parameters[0]);
//		Builder.callCPP.callTriangle(mInputValue.get(0).intValue(), mInputValue.get(1).intValue(), mInputValue.get(2).intValue());
//	   Builder.callCPP.callIsLeapYear(mInputValue.get(0).intValue());
//		public native boolean callIsValidDate(int day, int month, int year);
//		Builder.callCPP.callIsLeapYear((int)Builder.parameters[Builder.generatingParameterIndex]);
//		Builder.callCPP.callGetRootOfQuadraticF((float)Builder.parameters[0], (float)Builder.parameters[1], (float)Builder.parameters[2]);
//	    Builder.callCPP.callExpint(mInputValue2.get(0).intValue(), mInputValue2.get(1).doubleValue());
	    Builder.callCPP.callBessj(mInputValue2.get(0).intValue(), mInputValue2.get(1).doubleValue());
//	    Builder.callCPP.callJulday(mInputValue.get(0).intValue(), mInputValue.get(1).intValue(), mInputValue.get(2).intValue());
//	    Builder.callCPP.callPlgndr(mInputValue2.get(0).intValue(), mInputValue2.get(1).intValue(), mInputValue2.get(2).doubleValue());
//	    Builder.callCPP.callEi(mInputValue2.get(0).doubleValue());
//	    Builder.callCPP.callCaldat(mInputValue.get(0).intValue(), mInputValue.get(1).intValue(), mInputValue.get(2).intValue(), mInputValue.get(3).intValue());
//	    Builder.callCPP.callIcrc(mInputValue.get(0).shortValue(), mInputValue.get(1).longValue(), mInputValue.get(2).shortValue(), mInputValue.get(3).intValue());		
/*
	    try {
			parameterTypes = new Class[NUM_OF_PARAM];
			setParameterTypes();
			parameters = new Object[NUM_OF_PARAM];
			setParameters();
			c.getMethod(callFunctionName, parameterTypes).invoke(callCPP, parameters);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
*/  
		//结束计时
		Builder.function_time = Builder.function_time + System.currentTimeMillis();
		//记录目标程序被执行一次
		Builder.function_frequency++;
	}
	
	/**
	 * 获得个体的适应度值(针对整型行参）
	 * @param pathIndex
	 * @return
	 */
	public static double generateTestDataForInt(CFGPath path){ 
	    initialNodeInforInPath(path);    // 初始化路径节点信息（节点名，节点能源函数值）
	    return calEnergyValue(path); // 初始化能源函数值  
										
	}
	
	
	/**
	 * 获得个体的适应度值(针对浮点型或混合型行参）
	 * @param pathIndex
	 * @return
	 */
	public static double generateTestDataForOther(CFGPath path){   	
	    initialNodeInforInPath2(path);    // 初始化路径节点信息（节点名，节点能源函数值）
	    return calEnergyValue2(path); // 初始化能源函数值  	   	     
				
	}
	
	/**
	 *  初始化长度
	 */
	private static void initialLens()
	{
	/**  len:
	 *  
	    isLeapYear: 16
	    triangle: 8
	    expint : 27+52
	    bessj : 5+510
	    julday: 12
	    plgndr: 9+7
	    ei: 38+745
	    caldat: 17
	 */
		
		
		/**  length:
		 * 
		    isLeapYear: 16
		    triangle:24
		    expint: 27+52
		    bessj : 9+1020
		    julday: 21
		    plgndr: 11+9
		    ei:  60+60
		    caldat: 23
		 */
		List<SimpleCFGNode> snoList = Builder.targetPath.getPath();
		List<String> snoNameList = new ArrayList<String>();
		for(int i=0,size=snoList.size();i<size;i++)
		{
			snoNameList.add(snoList.get(i).getName());
		}
		
		/**
		 *  for bessj
		 */		
		if(!snoNameList.contains("node16"))
		{
			leftSideLen = 5;
			rightSideLen = 6;
			
			leftSideLength = 11;
			rightSideLength = 12;
		}
		else
		{
			leftSideLen = 5;
			rightSideLen = 9;
			
			leftSideLength = 9;
			rightSideLength = 1020;
		}
		/**
		 *  for expint
		 */
//		if(snoNameList.contains("node13"))
//		{
//			leftSideLen = 27;
//			rightSideLen = 1;
//			
//			leftSideLength = 27;
//			rightSideLength = 1;
//		}
//		else if(snoNameList.contains("node19") && snoNameList.contains("node26"))
//		{
//			leftSideLen = 4;
//			rightSideLen = 52;
//			
//			leftSideLength = 5;
//			rightSideLength = 52;
//		}
//		else if(snoNameList.contains("node19")&& snoNameList.contains("node26"))
//		{
//			leftSideLen = 4;
//			rightSideLen = 29;
//			
//			leftSideLength = 5;
//			rightSideLength = 29;
//		}
//		else
//		{
//			leftSideLen = 4;
//			rightSideLen = 3;
//			
//			leftSideLength = 5;
//			rightSideLength = 3;
//		}
		
		/**
		 *  for ei
		 */
/*		if(snoNameList.contains("node5") )
		{
			leftSideLen = 3;
			rightSideLen = 980;
			
			leftSideLength = 4;
			rightSideLength = 10;
		}
		else if(snoNameList.contains("node15") && !snoNameList.contains("node19"))
		{
			leftSideLen = 7;
			rightSideLen = 3;
			
			leftSideLength = 7;
			rightSideLength = 8; 
		}
		else if(snoNameList.contains("node15") && snoNameList.contains("node19"))
		{
			leftSideLen = 54;
			rightSideLen = 1;
		
     		leftSideLength = 55;
			rightSideLength = 2;
		}
		else
		{
			leftSideLen = 7;
			rightSideLen = 3;
			
			leftSideLength = 7;
			rightSideLength = 8; 
		}
*/		
		/**
		 * for julday
		 */
//		if(!snoNameList.contains("node11"))
//		{
//			leftSideLen  = 4;
//			leftSideLength = 21;
//		}
//		else if(snoNameList.contains("node3") && snoNameList.contains("node7"))
//		{
//			leftSideLen = 16;
//			leftSideLength = 26;
//		}
//		else if( snoNameList.contains("node3") && snoNameList.contains("node8"))
//		{
//			leftSideLen = 22;
//			leftSideLength =31;
//		}
//		else if(snoNameList.contains("node5") && snoNameList.contains("node7"))
//		{
//			leftSideLen = 17;
//			leftSideLength =27;
//		}
//		else if( snoNameList.contains("node5") && snoNameList.contains("node8"))
//		{
//			leftSideLen = 22;
//			leftSideLength =31;
//		}
//		else
//		{
//			leftSideLen = 12;
//			leftSideLength =23;
//		}
		
		/**
		 *  for icrc
		 */
//		{
//			leftSideLen = 8;
//			leftSideLength = 9;
//		}
		
		
		/**
		 *  general 
		 */
		if(isIntType == true)
		{
			len = leftSideLen;
			length = leftSideLength;  // 取值不该超过63
		}
		else
		{
			len = leftSideLen +rightSideLen;
			length = leftSideLength + rightSideLength; 
		}
	}		
	
	/**
	 *  初始化路径节点信息（节点名，节点能源函数值）,针对整形行参
	 * @param path
	 */
	private static void initialNodeInforInPath(CFGPath path)
	{
		if(nodeSetInPath == null )
		{
			nodeSetInPath = new ArrayList<String>();
		}
		else nodeSetInPath.clear();
		
		if(nodeEnergyValueSetInPath == null)
		{
			nodeEnergyValueSetInPath = new ArrayList<Double>();
		}
		else nodeEnergyValueSetInPath.clear();
		
		List<SimpleCFGNode> snoList = path.getPath();
		
		/* 置已完成能源函数值计算的节点集为空    */
		if(finishCalNodeSet == null)
		{
			finishCalNodeSet = new ArrayList<String>();  
		}
		else finishCalNodeSet.clear();
		
		for(int i=0,size=snoList.size();i<size;i++)
		{
			SimpleCFGNode node = snoList.get(i);
			String nodename = node.getName();
			nodeSetInPath.add(nodename);
			nodeEnergyValueSetInPath.add(new Double(calNodeEnergyValue(node)));
			finishCalNodeSet.add(nodename);  // 添加完成计算的节点名称
		}
	}
	
	/**
	 *  初始化路径节点信息（节点名，节点能源函数值），针对浮点、混合行参
	 * @param path
	 */
	private static void initialNodeInforInPath2(CFGPath path)
	{
		if(nodeSetInPath != null )
		{
			nodeSetInPath.clear();
		}
		else nodeSetInPath = new ArrayList<String>();
		
		if(nodeEnergyValueSetInPath != null)
		{
			nodeEnergyValueSetInPath.clear();
		}
		else nodeEnergyValueSetInPath = new ArrayList<Double>();
		
		List<SimpleCFGNode> snoList = path.getPath();
		
		/* 置已完成能源函数值计算的节点集为空    */
		if(finishCalNodeSet == null)
		{
			finishCalNodeSet = new ArrayList<String>();  
		}
		else finishCalNodeSet.clear();
		
		for(int i=0,size=snoList.size();i<size;i++)
		{
			SimpleCFGNode node = snoList.get(i);
			String nodeName = node.getName();
			nodeSetInPath.add(nodeName);
			nodeEnergyValueSetInPath.add(new Double(calNodeEnergyValue2(node)));
			finishCalNodeSet.add(nodeName);  // 添加完成计算的节点名称
		}
	}
	
	/**
	 *  初始化整型变量集
	 */
	private static void initialIntSet()
	{
		intSet = new TreeSet<Integer>();
		
		/**
		 *  for expint
		 */
//		intSet.add(new Integer(1));
//		intSet.add(new Integer(2+1));
//		intSet.add(new Integer(2+3));
//		intSet.add(new Integer(2+6));
//		intSet.add(new Integer(2+7));
//		intSet.add(new Integer(2+8));
//		intSet.add(new Integer(2+13));
//		intSet.add(new Integer(2+14));
//		intSet.add(new Integer(2+18));
//		
		/**
		 *  for bessj
		 */
//		intSet.add(new Integer(1));
//		intSet.add(new Integer(2+1));
//		intSet.add(new Integer(2+2));
//		intSet.add(new Integer(2+7));
//		intSet.add(new Integer(2+8));
//		intSet.add(new Integer(2+9));
//		intSet.add(new Integer(2+10));
//		intSet.add(new Integer(2+11));
//		intSet.add(new Integer(2+12));
//		intSet.add(new Integer(2+13));
//		intSet.add(new Integer(2+14));
//		intSet.add(new Integer(2+15));
		
		/**
		 *  for plgndr
		 */
//		intSet.add(new Integer(1));
//		intSet.add(new Integer(2));
//		intSet.add(new Integer(3+1));
//		intSet.add(new Integer(3+2));
//		intSet.add(new Integer(3+4));
//		intSet.add(new Integer(3+5));
//		intSet.add(new Integer(3+7));
//		intSet.add(new Integer(3+8));
//		intSet.add(new Integer(3+9));
//		intSet.add(new Integer(3+10));
//		intSet.add(new Integer(3+11));
//		intSet.add(new Integer(3+12));
//		intSet.add(new Integer(3+13));
//		intSet.add(new Integer(3+14));
		
		
		
	}
	
	/**
	 *  初始化限制集合（辅助变量）
	 */
	private static void initialConstraintSet()
	{
		positiveSet = new TreeSet<Integer>();
		negativeSet = new TreeSet<Integer>();
		unPositiveSet =new TreeSet<Integer>();
		unNegativeSet = new TreeSet<Integer>();
		unZeroSet = new TreeSet<Integer>();
		
		/** 
		 * for isLearYear
		 */
//		positiveSet.add(new Integer(1));
//		positiveSet.add(new Integer(2));
//		positiveSet.add(new Integer(3));
//		positiveSet.add(new Integer(4));
		
		/**
		 *  for triangle
		 */
//		positiveSet.add(new Integer(3+1));
//		positiveSet.add(new Integer(3+2));
//		positiveSet.add(new Integer(3+3));
//		positiveSet.add(new Integer(3+4));
//		positiveSet.add(new Integer(3+5));
//		positiveSet.add(new Integer(3+6));
//		unZeroSet.add(new Integer(3+7));
//		unZeroSet.add(new Integer(3+8));
//		unZeroSet.add(new Integer(3+9));
//		unZeroSet.add(new Integer(3+10));
//		unZeroSet.add(new Integer(3+11));
//		unPositiveSet.add(new Integer(3+12));	
//		unPositiveSet.add(new Integer(3+13));
//		unPositiveSet.add(new Integer(3+14));
//		unPositiveSet.add(new Integer(3+15));
//		unPositiveSet.add(new Integer(3+16));
//		unPositiveSet.add(new Integer(3+17));
		
		/**
		 *  for expint 
		 */
//		positiveSet.add(new Integer(2+10));
//		positiveSet.add(new Integer(2+17));
//		unPositiveSet.add(new Integer(2+11));
//		unPositiveSet.add(new Integer(2+12));
//		unNegativeSet.add(new Integer(2+3));
//		unNegativeSet.add(new Integer(2+4));
//		unNegativeSet.add(new Integer(2+14));
//		unNegativeSet.add(new Integer(2+19));
//		unNegativeSet.add(new Integer(2+20));
//		negativeSet.add(new Integer(2+1));
//		negativeSet.add(new Integer(2+2));
//		negativeSet.add(new Integer(2+15));
//		negativeSet.add(new Integer(2+16));
//		negativeSet.add(new Integer(2+18));
//		unZeroSet.add(new Integer(2+5));
//		unZeroSet.add(new Integer(2+6));
//		unZeroSet.add(new Integer(2+7));
//		unZeroSet.add(new Integer(2+8));
//		unZeroSet.add(new Integer(2+9));
//		unZeroSet.add(new Integer(2+13));
		
		/**
		 *  for bessj
		 */
//		positiveSet.add(new Integer(2+4));
//		positiveSet.add(new Integer(2+5));
//		positiveSet.add(new Integer(2+7));
//		positiveSet.add(new Integer(2+15));
////		unPositiveSet.add(new Integer(2+3));
//		negativeSet.add(new Integer(2+3));
//		unPositiveSet.add(new Integer(2+6));
//		unPositiveSet.add(new Integer(2+9));
//		unPositiveSet.add(new Integer(2+14));
//		negativeSet.add(new Integer(2+1));
//		negativeSet.add(new Integer(2+10));
//		negativeSet.add(new Integer(2+12));
//		unNegativeSet.add(new Integer(2+2));
//		unNegativeSet.add(new Integer(2+11));
//		unNegativeSet.add(new Integer(2+13));
//		unZeroSet.add(new Integer(2+8));
		
		/**
		 *  for julday
		 */
//		positiveSet.add(new Integer(3+4));
//		unPositiveSet.add(new Integer(3+5));
//		negativeSet.add(new Integer(3+3));
//		negativeSet.add(new Integer(3+7));
//		unNegativeSet.add(new Integer(3+2));
//		unNegativeSet.add(new Integer(3+6));
//		unZeroSet.add(new Integer(3+1));
		
		/**
		 * for plgndr
		 */
//		positiveSet.add(new Integer(3+2));
//		positiveSet.add(new Integer(3+3));
//		positiveSet.add(new Integer(3+7));
//		positiveSet.add(new Integer(3+14));
//		unPositiveSet.add(new Integer(3+5));
//		unPositiveSet.add(new Integer(3+6));
//		unPositiveSet.add(new Integer(3+8));
//		unPositiveSet.add(new Integer(3+13));
//		negativeSet.add(new Integer(3+1));
//		negativeSet.add(new Integer(3+10));
//		unNegativeSet.add(new Integer(3+4));
//		unNegativeSet.add(new Integer(3+9));
//		unZeroSet.add(new Integer(3+11));
//		unZeroSet.add(new Integer(3+12));
		
		/**
		 *  for ei
		 */
		positiveSet.add(new Integer(1+2));
		positiveSet.add(new Integer(1+5));
		unPositiveSet.add(new Integer(1+1));
		unPositiveSet.add(new Integer(1+4));
		negativeSet.add(new Integer(1+3));
		negativeSet.add(new Integer(1+6));
		negativeSet.add(new Integer(1+8));
		negativeSet.add(new Integer(1+10));
		unNegativeSet.add(new Integer(1+7));
		unNegativeSet.add(new Integer(1+9));
		unNegativeSet.add(new Integer(1+11));
		unNegativeSet.add(new Integer(1+12));
		
		/**
		 *  for caldat
		 */
//		positiveSet.add(new Integer(4+5));
//		positiveSet.add(new Integer(4+7));
//		positiveSet.add(new Integer(4+10));
//		unPositiveSet.add(new Integer(4+6));
//		unPositiveSet.add(new Integer(4+8));
//		unPositiveSet.add(new Integer(4+9));
//		negativeSet.add(new Integer(4+2));
//		negativeSet.add(new Integer(4+3));
//		negativeSet.add(new Integer(4+11));
//		unNegativeSet.add(new Integer(4+1));
//		unNegativeSet.add(new Integer(4+4));
//		unNegativeSet.add(new Integer(4+12));
		
		/**
		 * for Icrc
		 */
//		positiveSet.add(new Integer(4+5));
//		unPositiveSet.add(new Integer(4+6));
//		negativeSet.add(new Integer(4+2));
//		negativeSet.add(new Integer(4+3));
//		negativeSet.add(new Integer(4+7));
//		negativeSet.add(new Integer(4+10));
//		unNegativeSet.add(new Integer(4+1));
//		unNegativeSet.add(new Integer(4+4));
//		unNegativeSet.add(new Integer(4+8));
//		unNegativeSet.add(new Integer(4+9));
		
	}
	
	/**
	 * 计算路径的能源函数的值(针对整型行参）
	 * @param path
	 * @return
	 */
	private static double calEnergyValue(CFGPath path){ 
		
		double energyValue  = 0;     // 重新置为0

		for(int i=0;i<nodeEnergyValueSetInPath.size();i++)
		{
			energyValue += nodeEnergyValueSetInPath.get(i).doubleValue();
		}
		return energyValue;
	}
	
	/**
	 * 计算路径的能源函数的值(针对浮点型或混合型行参）
	 * @param path
	 */
	private static double calEnergyValue2(CFGPath path){  
		
		double energyValue2 = 0;     // 重新置为0

		for(int i=0,size=nodeEnergyValueSetInPath.size();i<size;i++)
		{
			energyValue2 += nodeEnergyValueSetInPath.get(i).doubleValue();
		}
		return energyValue2;
	}
	
	/**
	 * 计算分支节点的能源函数值(针对整型输入变量）
	 * @param node
	 * @return
	 */
	private static double calNodeEnergyValue(SimpleCFGNode node){
		String nodeName = node.getName();
		int number = Integer.parseInt(nodeName.trim().substring(4));
//		int upBoundary = 1<<(leftSideLength-1);
		
		/**
		 *  for isLeapYear 
		 */
//			if(node.getName().equals("node2"))
//			{
//			    return 0;	
//			}
//			else if(node.getName().equals("node3"))
//			{
//				return calBinaryDiff( inputValue.get(0)%4, auxilaryValue.get(0));
//			}
//			else if(node.getName().equals("node4"))
//			{
//				return calBinaryDiff( inputValue.get(0)%4, 0);
//			}
//			else if(node.getName().equals("node5"))
//			{
//			    return calBinaryDiff( inputValue.get(0)%400, 0);	
//			}
//			else if(node.getName().equals("node6"))
//			{
//			    return calBinaryDiff( inputValue.get(0)%400, auxilaryValue.get(1));	
//			}
//			else if(node.getName().equals("node7"))
//			{
//				return calBinaryDiff( inputValue.get(0)%100, 0);
//			}
//			else if(node.getName().equals("node8"))
//			{
//				return calBinaryDiff( inputValue.get(0)%100, auxilaryValue.get(2));
//			}
//			else return 0;
		
		/**
		 * for triangle
		 */
/*		if(node.getName().equals("node1") || node.getName().equals("node2"))
		{
			return 0;
		}
		else if(node.getName().equals("node3"))
		{
			return calBinaryDiff(inputValue.get(0).intValue(),auxilaryValue.get(0).intValue())+
					calBinaryDiff(inputValue.get(1).intValue(),auxilaryValue.get(1).intValue())+
					calBinaryDiff(inputValue.get(2).intValue(),auxilaryValue.get(2).intValue());
		}
		else if(node.getName().equals("node4"))
		{
			return calBinaryDiff(inputValue.get(0)+inputValue.get(1)-inputValue.get(2),auxilaryValue.get(3))+
					calBinaryDiff(inputValue.get(0)+inputValue.get(2)-inputValue.get(1),auxilaryValue.get(4))+
					calBinaryDiff(inputValue.get(2)+inputValue.get(1)-inputValue.get(0),auxilaryValue.get(5));
		}
		else if(node.getName().equals("node5"))
		{
			return calBinaryDiff(inputValue.get(0)-inputValue.get(1),0)*calBinaryDiff(inputValue.get(1)-inputValue.get(2),0);
		}
		else if(node.getName().equals("node6"))
		{
			return calBinaryDiff(inputValue.get(0)-inputValue.get(1),auxilaryValue.get(6))+calBinaryDiff(inputValue.get(1)-inputValue.get(2),auxilaryValue.get(7));
		}
		else if(node.getName().equals("node7"))
		{
			return calBinaryDiff(inputValue.get(0)*inputValue.get(0)+inputValue.get(1)*inputValue.get(1)-inputValue.get(2)*inputValue.get(2),0)*
					calBinaryDiff(inputValue.get(1)*inputValue.get(1)+inputValue.get(2)*inputValue.get(2)-inputValue.get(0)*inputValue.get(0),0)*
					calBinaryDiff(inputValue.get(0)*inputValue.get(0)+inputValue.get(2)*inputValue.get(2)-inputValue.get(1)*inputValue.get(1),0);
		}
		else if(node.getName().equals("node8"))
		{
			return calBinaryDiff(inputValue.get(0)*inputValue.get(0)+inputValue.get(1)*inputValue.get(1)-inputValue.get(2)*inputValue.get(2),auxilaryValue.get(8))*
					calBinaryDiff(inputValue.get(1)*inputValue.get(1)+inputValue.get(2)*inputValue.get(2)-inputValue.get(0)*inputValue.get(0),auxilaryValue.get(9))*
					calBinaryDiff(inputValue.get(0)*inputValue.get(0)+inputValue.get(2)*inputValue.get(2)-inputValue.get(1)*inputValue.get(1),auxilaryValue.get(10));
		}
		else if(node.getName().equals("node9"))
		{
			if(getPreNodeName(tpath,node).equals("node2"))
			{
				return calBinaryDiff(inputValue.get(0),auxilaryValue.get(14))*
						calBinaryDiff(inputValue.get(1),auxilaryValue.get(15))*
						calBinaryDiff(inputValue.get(2),auxilaryValue.get(16));
			}
			else if(getPreNodeName(tpath,node).equals("node3"))
			{
				return calBinaryDiff(inputValue.get(0)+inputValue.get(1)-inputValue.get(2),auxilaryValue.get(11))*
						calBinaryDiff(inputValue.get(0)+inputValue.get(2)-inputValue.get(1),auxilaryValue.get(12))*
						calBinaryDiff(inputValue.get(1)+inputValue.get(2)-inputValue.get(0),auxilaryValue.get(13));
			}
			else return 0;
		}
		else return 0;
*/		
		/**
		 *  for julday
		 */
//		int mm = inputValue.get(0).intValue();
//		int id = inputValue.get(1).intValue();
//		int iyyy = inputValue.get(2).intValue();
//		int jy  = iyyy;
//		
//		switch(number)
//		{
//		   case 3:
//		   {
//			   return (jy>=0?jy:upBoundary-jy);
//		   }
//		   case 4:
//		   {
//			   if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node2"))
//			   {
//				   return calBinaryDiff(jy,auxilaryValue.get(0));
//			   }
//			   else
//			   {
//				   return 0;
//			   }
//			   
//		   }
//		   case 5:
//		   {
//			   return calBinaryDiff(jy,auxilaryValue.get(2));
//		   }
//		   case 6:
//		   {
//			   if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node4"))
//			   {
//				   return calBinaryDiff(jy,auxilaryValue.get(1));
//			   }
//			   else
//			   {
//				   return 0;
//			   }
//		   }
//		   case 7:
//		   {
//			   return calBinaryDiff(mm-2,auxilaryValue.get(3));
//		   }
//		   case 8:
//		   {
//			   return calBinaryDiff(mm-2,auxilaryValue.get(4));
//		   }
//		   case 11:
//		   {
//			   int IGREG = 15+31*(10+12*1582);
//			   return calBinaryDiff(id+31*(mm+12*iyyy)-IGREG,auxilaryValue.get(5));
//		   }
//		   case 12:
//		   {
//			   if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node10"))
//			   {
//				   int IGREG = 15+31*(10+12*1582);
//				   return calBinaryDiff(id+31*(mm+12*iyyy)-IGREG,auxilaryValue.get(6));
//			   }
//			   else
//			   {
//				   return 0;
//			   }
//		   }
//		   default:
//		   {
//			   return 0;
//		   }
//		}
		
		/**
		 *  for caldat
		 */
//		int IGREG = 2299161;
//		int ja,jalpha,jb,jc,jd,je;
//		int julian = inputValue.get(0).intValue();
//		int mm = inputValue.get(1).intValue();
//		int id = inputValue.get(2).intValue();
//		int iyyy = inputValue.get(3).intValue();
//		switch(number)
//		{
//			case 3:
//			{
//				
//				return calBinaryDiff(inputValue.get(0)-IGREG,auxilaryValue.get(0));
//			}
//			case 4:
//			{
//				return calBinaryDiff(inputValue.get(0)-IGREG,auxilaryValue.get(1));
//			}
//			case 6:
//			{
//				return calBinaryDiff(inputValue.get(0),auxilaryValue.get(3));
//			}
//			case 5:
//			{
//				
//				return calBinaryDiff(inputValue.get(0),auxilaryValue.get(2));
//			}
//			case 9:
//			{
//				if(isNodeInPath("node3",tpath)==true)
//				{
//					jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//					ja=julian+1+jalpha-(int)(0.25*jalpha);
//				}
//				else if(isNodeInPath("node5",tpath)==true)
//				{
//					ja=julian+36525*(1-julian/36525);
//				}
//				else  //(isNodeInPath("node6",tpath)==true)
//				{
//					ja = julian;
//				}
//				jb=ja+1524;
//				jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
//				jd=(int)(365*jc+(0.25*jc));
//				je=(int)((jb-jd)/30.6001);
////				id=jb-jd-(int)(30.6001*je);
//				mm=je-1;
//				
//				return calBinaryDiff(mm-12,auxilaryValue.get(4));
//			}
//			case 10:
//			{
//				if(!finishCalNodeSet.contains("node9"))
//				{
//					if(isNodeInPath("node3",tpath)==true)
//					{
//						jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//						ja=julian+1+jalpha-(int)(0.25*jalpha);
//					}
//					else if(isNodeInPath("node5",tpath)==true)
//					{
//						ja=julian+36525*(1-julian/36525);
//					}
//					else  //(isNodeInPath("node6",tpath)==true)
//					{
//						ja = julian;
//					}
//					jb=ja+1524;
//					jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
//					jd=(int)(365*jc+(0.25*jc));
//					je=(int)((jb-jd)/30.6001);
////					id=jb-jd-(int)(30.6001*je);
//					mm=je-1;
//					return calBinaryDiff(mm-12,auxilaryValue.get(5));
//				}
//				else return 0;
//			}
//			case 12:
//			{
//				if(isNodeInPath("node3",tpath)==true)
//				{
//					jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//					ja=julian+1+jalpha-(int)(0.25*jalpha);
//				}
//				else if(isNodeInPath("node5",tpath)==true)
//				{
//					ja=julian+36525*(1-julian/36525);
//				}
//				else  //(isNodeInPath("node6",tpath)==true)
//				{
//					ja = julian;
//				}
//				jb=ja+1524;
//				jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
//				jd=(int)(365*jc+(0.25*jc));
//				je=(int)((jb-jd)/30.6001);
////				id=jb-jd-(int)(30.6001*je);
//				mm=je-1;
//				if(isNodeInPath("node9",tpath)==true)
//				{
//					mm -= 12;
//				}
////				iyyy=jc-4715;
//				return calBinaryDiff(mm-2,auxilaryValue.get(6));
//			}
//			case 13:
//			{
//				if(!finishCalNodeSet.contains("node12"))
//				{
//					if(isNodeInPath("node3",tpath)==true)
//					{
//						jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//						ja=julian+1+jalpha-(int)(0.25*jalpha);
//					}
//					else if(isNodeInPath("node5",tpath)==true)
//					{
//						ja=julian+36525*(1-julian/36525);
//					}
//					else  //(isNodeInPath("node6",tpath)==true)
//					{
//						ja = julian;
//					}
//					jb=ja+1524;
//					jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
//					jd=(int)(365*jc+(0.25*jc));
//					je=(int)((jb-jd)/30.6001);
////					id=jb-jd-(int)(30.6001*je);
//					mm=je-1;
//					if(isNodeInPath("node9",tpath)==true)
//					{
//						mm -= 12;
//					}
////					iyyy=jc-4715;
//					return calBinaryDiff(mm-2,auxilaryValue.get(7));
//				}
//				else return 0;
//			}
//			case 14:
//			{
//				if(isNodeInPath("node3",tpath)==true)
//				{
//					jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//					ja=julian+1+jalpha-(int)(0.25*jalpha);
//				}
//				else if(isNodeInPath("node5",tpath)==true)
//				{
//					ja=julian+36525*(1-julian/36525);
//				}
//				else  //(isNodeInPath("node6",tpath)==true)
//				{
//					ja = julian;
//				}
//				jb=ja+1524;
//				jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
////				jd=(int)(365*jc+(0.25*jc));
////				je=(int)((jb-jd)/30.6001);
////				id=jb-jd-(int)(30.6001*je);
////				mm=je-1;
////				if(isNodeInPath("node9",tpath)==true)
////				{
////					mm -= 12;
////				}
//				iyyy=jc-4715;
//				if(isNodeInPath("node12",tpath)==true)
//				{
//					--iyyy;
//				}
//				return calBinaryDiff(iyyy,auxilaryValue.get(8));
//			}
//			case 15:
//			{
//				if(!finishCalNodeSet.contains("node14"))
//				{
//					if(isNodeInPath("node3",tpath)==true)
//					{
//						jalpha=(int)(((julian-1867216)-0.25)/36524.25);
//						ja=julian+1+jalpha-(int)(0.25*jalpha);
//					}
//					else if(isNodeInPath("node5",tpath)==true)
//					{
//						ja=julian+36525*(1-julian/36525);
//					}
//					else  //(isNodeInPath("node6",tpath)==true)
//					{
//						ja = julian;
//					}
//					jb=ja+1524;
//					jc=(int)(6680.0+((jb-2439870)-122.1)/365.25);
////					jd=(int)(365*jc+(0.25*jc));
////					je=(int)((jb-jd)/30.6001);
////					id=jb-jd-(int)(30.6001*je);
////					mm=je-1;
////					if(isNodeInPath("node9",tpath)==true)
////					{
////						mm -= 12;
////					}
//					iyyy=jc-4715;
//					if(isNodeInPath("node12",tpath)==true)
//					{
//						--iyyy;
//					}
//					return calBinaryDiff(iyyy,auxilaryValue.get(9));
//				}
//				else return 0;
//			}
//			case 16:
//			{
//				return calBinaryDiff(inputValue.get(0),auxilaryValue.get(10));
//			}
//			case 17:
//			{
//				if(!finishCalNodeSet.contains("node16"))
//				{
//					return calBinaryDiff(inputValue.get(0),auxilaryValue.get(11));
//				}
//				else return 0;
//			}
//			default:
//			{
//				return 0;
//			}
//		}
		
		/**
		 * for icrc
		 */
		short crc = inputValue.get(0).shortValue();
		long len = inputValue.get(1).longValue();
		short jinit = inputValue.get(2).shortValue();
		int jrev = inputValue.get(3).intValue();
		
		switch(number)
		{
			case 7:
			{
				return calBinaryDiff(jinit,auxilaryValue.get(0));
			}
			case 8:
			{
				return calBinaryDiff(jinit,auxilaryValue.get(1));
			}
			case 9:
			{
				return calBinaryDiff(jrev,auxilaryValue.get(2));
			}
			case 10:
			{
				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node8"))
				{
					return calBinaryDiff(jrev,auxilaryValue.get(3));
				}
				else
				{
					return 0;
				}
			}
			case 11:
			{
				return calBinaryDiff(1-len,auxilaryValue.get(5));
			}
			case 15:
			{
				if(!finishCalNodeSet.contains("node11"))
				{
					return calBinaryDiff(1-len,auxilaryValue.get(4));
				}
				else
				{
					return 0;
				}
				
			}
			case 12:
			{
				return calBinaryDiff(jrev,auxilaryValue.get(6));
			}
			case 13:
			{
				return calBinaryDiff(jrev,auxilaryValue.get(7));
			}
			case 16:
			{
				return calBinaryDiff(jrev,auxilaryValue.get(8));
			}
			case 17:
			{
				return calBinaryDiff(jrev,auxilaryValue.get(9));
			}
			default:
			{
				return 0;
			}
		}
		
}
	
	
	/**
	 * 计算分支节点的能源函数值(针对浮点型或混合型输入变量）
	 * @param node
	 * @return
	 */
	private static double calNodeEnergyValue2(SimpleCFGNode node){
		
		String nodeName = node.getName();
		int number = Integer.parseInt(nodeName.trim().substring(4));
//		double upBound = 1<<(leftSideLength-1);
		
		/**
		 *  for expint
		 */
//		int n = inputValue2.get(0).intValue();
//		double x = inputValue2.get(1);
//		double EULER=0.577215664901533;
//		double EPS=(2.22044604925031308085e-16);
//		double max=1.79769313486231570815e+308;
//		double BIG = max*EPS;
//		switch(number)
//		{
//			case 3:
//			{
//				double r1 = (x>=0?x:(-x+upBound));
//				double r2 = (n>=0?n:(-n+upBound));
//				double r3 = (n-1>=0?n-1:1-n+upBound);
//				return calBinaryDiff(n,auxilaryValue2.get(0).intValue())*
//						calBinaryDiff2(x,auxilaryValue2.get(1))*
//					   (r1+r2*r3);
//			}
//			case 4:
//			{
//				return calBinaryDiff(n,auxilaryValue2.get(2).intValue())+
//						calBinaryDiff2(x,auxilaryValue2.get(3))+
//						calBinaryDiff2(x,auxilaryValue2.get(4))*
//						(calBinaryDiff(n,auxilaryValue2.get(5).intValue())+
//						  calBinaryDiff(n-1,auxilaryValue2.get(6).intValue()))	;
//			}
//			case 5:
//			{
//				double r2 = (n>=0?n:(-n+upBound));
//				return r2;
//			}
//			case 6:
//			{
//				return calBinaryDiff(n,auxilaryValue2.get(7).intValue());
//			}
//			case 7:
//			{
//				double r1 = (x>=0?x:(-x+upBound));
//				return r1;
//			}
//			case 8:
//			{
//				return calBinaryDiff2(x,auxilaryValue2.get(8));
//			}
//			case 9:
//			{
//				return calBinaryDiff2(x-1,auxilaryValue2.get(9));
//			}
//			case 10:
//			{
//				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node12"))
//				{
//						double b = n+x;
//						double c = BIG;
//						double d = 1.0/b;
//			           double a = -1*n;
//			           b += 2.0;
//			           d = 1.0/(a*d+b);
//			           c = b+a/c;
//			           double del = c*d;
//						 return calBinaryDiff2(Math.abs(del-1.0)-EPS,auxilaryValue2.get(16));
//				}
//				else
//				{
//					return 0;
//				}
//			}
//			case 13:
//			{
//				double b = n+x;
//				double c = BIG;
//				double d = 1.0/b;
//	           double a = -1*n;
//	           b += 2.0;
//	           d = 1.0/(a*d+b);
//	           c = b+a/c;
//	           double del = c*d;
//				 return calBinaryDiff2(Math.abs(del-1.0)-EPS,auxilaryValue2.get(10));
//			}
//			case 15:
//			{
//				return calBinaryDiff2(x-1,auxilaryValue2.get(11));
//			}
//			case 16:
//			{
//				double ans =(n-1!=0 ? 1.0/(n-1) : -Math.log(x)-EULER);
//			    double del;
//			    double firstNumber;
//			    if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node25") &&
//			        isNodeInPath("node19",tpath))
//			     {
//						del = x/(2-n);
//						ans += del;
//						firstNumber = Math.abs(del)-Math.abs(ans)*EPS;
//						return calBinaryDiff2(firstNumber,auxilaryValue2.get(18));
//				}
//				else if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node25") &&
//			        isNodeInPath("node20",tpath))
//				{
//					double psi = -EULER;
//					for(int ii=1;ii<=n-1;ii++)
//					{
//						psi += 1.0/ii;
//					}
//					del = -x*(psi-Math.log(x));
//					ans += del;
//					firstNumber = Math.abs(del)-Math.abs(ans)*EPS;
//					return calBinaryDiff2(firstNumber,auxilaryValue2.get(19));
//				}
//			    else
//			    {
//			    	return 0;
//			    }
//			}
//			case 19:
//			{
//				return calBinaryDiff(n-2,auxilaryValue2.get(12).intValue());
//			}
//			case 20:
//			{
//				double r = (n-2>=0?n-2:2-n+upBound);
//				return r;
//			}
//			case 22:
//			{
//				return calBinaryDiff(n-2,auxilaryValue2.get(13).intValue());
//			}
//			case 23:
//			{
//				return calBinaryDiff(n-2,auxilaryValue2.get(17).intValue());
//			}
//			case 26:
//			{
//				double ans =(n-1!=0 ? 1.0/(n-1) : -Math.log(x)-EULER);
//				double del;
//				double firstNumber;
//				if(isNodeInPath("node19",tpath))
//				{
//					del = x/(2-n);
//					ans += del;
//					firstNumber = Math.abs(del)-Math.abs(ans)*EPS;
//					return calBinaryDiff2(firstNumber,auxilaryValue2.get(14));
//				}
//				else //isNodeInPath("node20",tpath)
//				{
//					double psi = -EULER;
//					for(int ii=1;ii<=n-1;ii++)
//					{
//						psi += 1.0/ii;
//					}
//					del = -x*(psi-Math.log(x));
//					ans += del;
//					firstNumber = Math.abs(del)-Math.abs(ans)*EPS;
//					return calBinaryDiff2(firstNumber,auxilaryValue2.get(15));
//				}
//			}
//			default:
//			{
//				return 0;
//			}
//		}
		
		
		/**
		 *  for bessj
		 */
		double dmin = 2.22507385850720138309e-308;
		double boundary = 1<<(leftSideLength-1);
		switch(number){
					
			case 3:
			{
				return calBinaryDiff(inputValue2.get(0).longValue()-2,auxilaryValue2.get(0).longValue());  // 整
			}
			case 4:
    		{
				if(!finishCalNodeSet.contains("node3"))
				{
					return calBinaryDiff(inputValue2.get(0).longValue()-2,auxilaryValue2.get(1).longValue()); // 整
				}
				else
				{
					return 0;
				}
			}
			case 6:
			{
				return calBinaryDiff2(inputValue2.get(1)*inputValue2.get(1)-8*dmin,auxilaryValue2.get(2));
			}
			case 7:
			{
				return calBinaryDiff2(inputValue2.get(1)*inputValue2.get(1)-8*dmin,auxilaryValue2.get(3));
			}
			case 8:
			{
				return calBinaryDiff2(Math.abs(inputValue2.get(1))-inputValue2.get(0),auxilaryValue2.get(4));
			}
			case 10:
			{
				return calBinaryDiff(1-inputValue2.get(0).longValue(),auxilaryValue2.get(9).longValue());  // 整
			}
			case 11:
			{
				if(!isNodeInPath("node10",Builder.targetPath))
				{
					return calBinaryDiff(1-inputValue2.get(0).longValue(),auxilaryValue2.get(10).longValue());  // 整
				}
				else
				{
					return 0;
				}
			}
			case 12:
			{
				return calBinaryDiff2(Math.abs(inputValue2.get(1))-inputValue2.get(0),auxilaryValue2.get(5));
			}
			case 13:
			{
				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node20"))
				{
						int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));
						return calBinaryDiff(m-inputValue2.get(0).longValue(),auxilaryValue2.get(7).longValue());  // 整
				}
				else 
				{
					return 0;
				}
			}
			case 14:
			{
					int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));  // 整
					return calBinaryDiff(m,auxilaryValue2.get(14).longValue());
			}
			case 16:
			{
					int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));  // 整
					int IEXP = 512;
					int z = (int)(Math.getExponent(m*2.0/Math.abs(inputValue2.get(1))))-IEXP;
					return calBinaryDiff(z,auxilaryValue2.get(6).longValue());
			}
			case 17:
			{
				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node15"))
				{
						int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));
						int IEXP = 512;
						int z = (int)(Math.getExponent(m*2.0/Math.abs(inputValue2.get(1))))-IEXP;
						return calBinaryDiff(z,auxilaryValue2.get(8).longValue());   // 整
				}
				else 
				{
					return 0;
				}
				
			}
			case 21: // 整
			{
					int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));
//				    return calBinaryDiff2(m-inputValue2.get(0),0);
				    if(m-inputValue2.get(0).intValue()>=0)
				    {
				    	return m-inputValue2.get(0).intValue();
				    }
				    else
				    {
				    	return -(m-inputValue2.get(0).intValue())+boundary;
				    }
			}
			case 22: // 整
			{
				if(!finishCalNodeSet.contains("node14"))
				{
					int m = inputValue2.get(0).intValue()+(int)(Math.sqrt(160*inputValue2.get(0)));
				    return calBinaryDiff(m,auxilaryValue2.get(13).longValue());
				}
				else
				{
					return 0;
				}
			}
			default:
			{
				return 0;
			}
		}
		
		/**
		 *  for plgndr
		 */
//		switch(number)
//		{
//			case 3:
//			{
//				return calBinaryDiff2(inputValue2.get(1),auxilaryValue2.get(0))*
//						calBinaryDiff2(inputValue2.get(1)-inputValue2.get(0),auxilaryValue2.get(1))*
//						calBinaryDiff2(Math.abs(inputValue2.get(2))-1.0,auxilaryValue2.get(2));
//			}
//			case 4:
//			{
//				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node2"))
//				{
//					return calBinaryDiff2(inputValue2.get(1),auxilaryValue2.get(3))+
//							calBinaryDiff2(inputValue2.get(1)-inputValue2.get(0),auxilaryValue2.get(4))+
//							calBinaryDiff2(Math.abs(inputValue2.get(2))-1.0,auxilaryValue2.get(5));
//				}
//				else return 0;
//			}
//			case 6:
//			{
//				return calBinaryDiff2(inputValue2.get(1),auxilaryValue2.get(6));
//			}
//			case 8:
//			{
//				return calBinaryDiff2(inputValue2.get(1)-1,auxilaryValue2.get(8));
//			}
//			case 9:
//			{
//				if(getPreNodeName(tpath,node).equals("node5"))
//				{
//					return calBinaryDiff2(inputValue2.get(1),auxilaryValue2.get(7));
//				}
//				else if(getPreNodeName(tpath,node).equals("node7")&& !isNodeInPath("node8",tpath))
//				{
//					return calBinaryDiff2(inputValue2.get(1)-1,auxilaryValue2.get(9));
//				}
//				else return 0;
//			}
//			case 10:
//			{
//				return calBinaryDiff2(inputValue2.get(0)-inputValue2.get(1),0);
//			}
//			case 11:
//			{
//				return calBinaryDiff2(inputValue2.get(0)-inputValue2.get(1),auxilaryValue2.get(10));
//			}
//			case 13:
//			{
//				return calBinaryDiff2(inputValue2.get(0)-inputValue2.get(1)-1,0);
//			}
//			case 14:
//			{
//				return calBinaryDiff2(inputValue2.get(0)-inputValue2.get(1)-1,auxilaryValue2.get(11));
//			}
//			case 15:
//			{
//				return calBinaryDiff2(inputValue2.get(1)-inputValue2.get(0)+2,auxilaryValue2.get(12));
//			}
//			case 16:
//			{
//				if(!isNodeInPath("node15",tpath))
//				{
//					return calBinaryDiff2(inputValue2.get(1)-inputValue2.get(0)+2,auxilaryValue2.get(13));
//				}
//			}
//			default:
//			{
//				return 0;
//			}
//		}
		
		/**
		 *  for ei
		 */
/*		double EPS = 2.22044604925031308085e-16;
		double FPMIN = 2.22507385850720138309e-308/EPS;
		double x = inputValue2.get(0).doubleValue();
		switch(number)
		{
			case 3:
			{
				return calBinaryDiff2(x,auxilaryValue2.get(0));
			}
			case 4:
			{
				return calBinaryDiff2(x,auxilaryValue2.get(1));
			}
			case 5:
			{
				return calBinaryDiff2(x-FPMIN,auxilaryValue2.get(2));
			}
			case 6:
			{
				return calBinaryDiff2(x-FPMIN,auxilaryValue2.get(11));
			}
			case 7:
			{
				return calBinaryDiff2(x+Math.log(EPS),auxilaryValue2.get(3));
			}
			case 8:
			{
				if(finishCalNodeSet.get(finishCalNodeSet.size()-1).equals("node10"))
				{
					return calBinaryDiff2(x,auxilaryValue2.get(6));
				}
				else return 0;
			}
			case 11:
			{
					return calBinaryDiff2(x,auxilaryValue2.get(5));
			}
			case 15:
			{
				return calBinaryDiff2(x+Math.log(EPS),auxilaryValue2.get(4));
			}
			case 19:
			{
					return calBinaryDiff2(1/x-EPS,auxilaryValue2.get(7));
			}
			case 20:
			{
					return calBinaryDiff2(1/x-EPS,auxilaryValue2.get(8));
			}
			case 21:
			{
					return calBinaryDiff2(1/x-1,auxilaryValue2.get(9));
			}
			case 22:
			{
					return calBinaryDiff2(1/x-1,auxilaryValue2.get(10));
			}
			default:
			{
				return 0;
			}
		}
*/		
	}
	
	/**
	 * 计算两个整数的二进制表示（反码）之间的加权海明距离
	 * @param number1
	 * @param number2
	 * @return
	 */
    private static long calBinaryDiff(long number1,long number2)
    {
    	long maixExp = 1<< (leftSideLength-1);
    	/**
    	 *  当参数中有0时     
    	 */
    	if(number1 >=0 && number2 == 0)
    	{
    		return number1;
    	}
    	if(number1 <0 && number2 ==0)
    	{
    		return (-number1)+maixExp;
    	}
    	if(number2 >0 && number1 == 0)
    	{
    		return number2;
    	}
    	if(number2 <0 && number1 ==0)
    	{
    		return (-number2)+maixExp;
    	}
    	
    	/**
    	 *  当参数中没有0时  
    	 */
    	long dif = 0;
    	/* 将参数的绝对值转化为二进制串（反码）    */
    	boolean flag=true;   // 参数符号是否相同,相同为true，不同为false 
    	if(number1>0 && number2<0 ||(number1<0 && number2>0)) flag = false;
    	
    	String s1 = Long.toBinaryString(Math.abs(number1));
    	String s2 = Long.toBinaryString(Math.abs(number2));
    	int len1 = s1.length();
    	int len2 = s2.length();
    	
    	/* 对齐字符串，计算多出部分的加权海明距离    */
    	String ss1,ss2;
    	if(len1>len2)
    	{
    		String over1 = s1.substring(0, len1-len2);
    		long overValue1 = Long.parseLong(over1, 2)*(1<<len2);
    		dif += overValue1;
    		ss1 = s1.substring(len1-len2);
    		ss2 = s2;
    	}
    	else if(len1<len2)
    	{
    		String over2 = s2.substring(0, len2-len1);
    		long overValue2 = Long.parseLong(over2, 2)*(1<<len1);
    		dif += overValue2;
    		ss2 = s2.substring(len2-len1);
    		ss1 = s1;
    	}
    	else
    	{
    		ss1 = s1;
    		ss2 = s2;
    	}
    	
    	/* 计算对齐部分的加权海明距离     */
    	char[] c1 = ss1.toCharArray();
    	char[] c2 = ss2.toCharArray();
    	char[] c = c1.clone();
    	for(int i=0,size=c.length;i<size;i++)
    	{
    		c[i] = (char)(c1[i]^c2[i]-48);  // 将数字1转化为字符‘1’，数字0转化为字符‘0’
    	}
    	String diffString = new String(c);
    	dif += Long.parseLong(diffString, 2);
    	
    	/* 若参数不同号，结果需要加上符号位的权值    */
    	if(flag == false)
    	{
    		dif += maixExp;
    	}
    	
    	return dif ;
    }
    
    /**
     * 计算两个浮点数的二进制表示（反码）之间的加权海明距离
     * @param number1
     * @param number2
     * @return
     */
    private static double calBinaryDiff2(double number1,double number2)
     {
    	
    	/** 当参数含NaN或无穷时
    	 * 
    	 */
    	if(Double.isNaN(number1) || Double.isNaN(number2))
    	{
    		return Double.NaN;
    	}
    	if(Double.isInfinite(number1) || Double.isInfinite(number2))
    	{
    		return Double.POSITIVE_INFINITY;
    	}
    	
    	/**
    	 *  当参数中有0时     
    	 */
//    	double downBoundary = Math.pow(2, -rightSideLength-1);
    	double upBoundary = 1<<(leftSideLength-1);
    	if(Double.compare(number1, 0)>=0 && Double.compare(number2, 0)==0)
    	{
    		return number1;
    	}
    	if(Double.compare(number1, 0)<0 && Double.compare(number2, 0)==0)
    	{
    		return (-number1) + upBoundary;
    	}
    	if(Double.compare(number1, 0)==0 && Double.compare(number2, 0)>=0)
    	{
    		return number2;
    	}
    	if(Double.compare(number1, 0)==0 && Double.compare(number2, 0)<0)
    	{
    		return (-number2) + upBoundary;
    	}
    	
    	/**
    	 *  当参数不为0 
    	 */
    	double dif = 0;
    	boolean flag = true;   // 参数符号是否相同,相同为true，不同为false
    	/* 将参数转化为16进制串                */
    	String hexString1 = Double.toHexString(number1);
    	String hexString2 = Double.toHexString(number2);
    	/* 判断2个参数的符号是否相同    */
    	if(hexString1.charAt(0)!= hexString2.charAt(0))
    	{
    		flag = false;
    	}
    	/* 忽略小数点和幂，将16进制串转化为二进制串（例如，将 0x1.12p3 的16进制串112转化为100010010      */
    	int indexOfX1 = hexString1.indexOf('x');
    	int indexOfPoint1 = hexString1.indexOf('.');
    	int indexOfP1 = hexString1.indexOf('p');
    	char char1 = hexString1.charAt(indexOfX1+1);
    	String subString1 = hexString1.substring(indexOfPoint1+1, indexOfP1);
    	StringBuffer sb1 = new StringBuffer(14);
    	String hexString11 = sb1.append(1).append(subString1).toString();
    	
    	int indexOfX2 = hexString2.indexOf('x');
    	int indexOfPoint2 = hexString2.indexOf('.');
    	int indexOfP2 = hexString2.indexOf('p');
    	char char2 = hexString2.charAt(indexOfX2+1);
    	String subString2 = hexString2.substring(indexOfPoint2+1, indexOfP2);
    	StringBuffer sb2 = new StringBuffer(14);
    	String hexString22 = sb2.append(1).append(subString2).toString();
    	
    	long l1 = Long.parseLong(hexString11, 16);
    	long l2 = Long.parseLong(hexString22, 16);
    	String tempString1 = Long.toBinaryString(l1);
    	String tempString2 = Long.toBinaryString(l2);
    	StringBuffer bsb1 = new StringBuffer(tempString1);
    	bsb1.setCharAt(0, char1);
    	String binString1 = bsb1.toString();
    	StringBuffer bsb2 = new StringBuffer(tempString2);
    	bsb1.setCharAt(0, char2);
    	String binString2 = bsb2.toString();
    	
    	/* 确定二进制串的幂      */
    	String expStr1 = hexString1.substring(indexOfP1+1);
    	String expStr2 = hexString2.substring(indexOfP2+1);
    	int tempExp1 = Integer.parseInt(expStr1);
    	int tempExp2 = Integer.parseInt(expStr2);
    	int exp1 = tempExp1-(indexOfP1-indexOfPoint1-1)*4;  // 根据小数点位置修正幂
    	int exp2 = tempExp2-(indexOfP2-indexOfPoint2-1)*4;
    	
       /* 计算整数部分的海明距离    */
    	dif += calBinaryWHD(binString1,exp1,binString2,exp2);
    	
    	/* 计算小数部分的海明距离    */
    	dif += calPoinBinaryWHD(binString1,tempExp1,binString2,tempExp2);
    	
    	/* 根据符号位标志修正最终结果   */
    	if(flag == false)
    	{
    		dif+= upBoundary;
    	}
    	return dif;
    }
	
    /**
     * 计算两个表示浮点数的二进制串的整数部分的加权海明距离,第一个串为 s10...0 (e1个0） ， 第二个串为 s20...0 (e2个0）,注意这里 s1,s2必须只由0或1组成
     * @param s1: h0b1b2...b(4*k1), k1<=13, h0,bi为0或1
     * @param e1: 
     * @param s2: H0B1B2...B(4*k2), k2<=13，H0，Bj为0或1
     * @param e2: 
     * @return
     */
    private static double calBinaryWHD(String s1,int e1,String s2,int e2)
    {
    	double whd = 0.0;
    	int len1 = s1.length();
    	int len2 = s2.length();
    	int d;
    	double exp1 = Math.pow(2, e1);
    	double exp2 = Math.pow(2, e2);
    	double exp3 = Math.pow(2, e2+len2);
    	double valueofs1 = (double)Long.parseLong(s1, 2);
    	double valueofs2 = (double)Long.parseLong(s2, 2);
    	/**
    	 *  当浮点数的整数部分都为0
    	 */
    	if(len1+e1<=0 && len2+e2<=0)
    	{
    		return 0;
    	}
    	
    	/**
    	 *  当一个浮点数的整数部分为0，另一个不为0
    	 */
    	else if(len1+e1>0 && len2+e2<=0)
    	{
    		if(e1>=0)  //第一个浮点数的整数部分包含s1 
    		{
    			return valueofs1*exp1;
    		}
    		else  //第一个浮点数的整数部分包含s1的子串 h0b1b2...b(len1+e1-1) 
    		{
    			String ps1 = s1.substring(0, len1+e1);
    			return (double)Long.parseLong(ps1, 2);
    		}
    	}
    	else if(len1+e1<=0 && len2+e2>0)
    	{
    		if(e2>=0)  //第二个浮点数的整数部分包含s2 
    		{
    			return valueofs2*exp2;
    		}
    		else  //第二个浮点数的整数部分包含s2的子串 H0B1B2...B(len2+e2-1) 
    		{
    			String ps2 = s2.substring(0, len2+e2);
    			return (double)Long.parseLong(ps2, 2);
    		}
    	}
    	
    	/** 
    	 *  当两个浮点数的整数部分都不为0
    	 *  首先比较两个串的长度，计算出长串多出部分的海明距离，再对剩余字符串进行异或运算，得差异字符串，结合幂，计算出对齐部分的海明距离。
    	 *  将两部分的海明距离相加，得到最终结果    
    	 */  
    	else if(len1+e1>len2+e2 ) // len1+e1>0 && len2+e2>0
    	{
    		d = len1+e1-len2-e2;
    		/* 多出部分在s1中    */
    		if(d<=len1 && e2>=0 && e1>=0)  // 第一个浮点数的整数部分包含s1，第二个浮点数的整数部分包含s2
    		{
    			/**
    			 * 计算多出部分的海明距离
    			 */
    			String ps1 = s1.substring(0,d);    // 多处部分字符串              
    			whd += ((double)Long.parseLong(ps1, 2)*exp3);  // 加上多出部分的海明距离
    			
    			/**
    			 * 计算对齐部分的海明距离
    			 */
    			String left1 = s1.substring(d);   // 剩余字符串
    			int leftlen1 = left1.length();
    			
    			/* 将字符串转化为字符数组     */
    			char[] c1 = left1.toCharArray();
    			char[] c2 = s2.toCharArray();
    			
    			/* 构造异或字符串，结合幂，计算出对齐部分的海明距离   */
    			if(leftlen1 >= len2)
    			{
    				char[] c = c1.clone();
    				for(int i=0,size=c2.length;i<size;i++)
    				{
    					c[i]= (char)(c1[i]^c2[i]-48);
    				}
    				String  xorStr = new String(c);  // 异或字符串
    				whd += ((double)Long.parseLong(xorStr, 2)*exp1);  // 加上对齐部分的海明距离
    			}
    			else 
    			{
    				char[] c = c2.clone();
    				for(int i=0,size=c1.length;i<size;i++)
    				{
    					c[i]= (char)(c1[i]^c2[i]-48);
    				}
    				String  xorStr = new String(c);  // 异或字符串
    				whd += ((double)Long.parseLong(xorStr, 2)*exp2);  // 加上对齐部分的海明距离
    			}
    		} //if(d <= len1)
    		else if(d<=len1 && e1>=0 && e2<0) //第一个浮点数的整数部分包含s1，第二个浮点数的整数部分包含s2的子串 H0B1B2...B(len2+e2-1)
    		{
    			
    			/**
    			 * 计算多出部分的海明距离
    			 */
    			String ps1 = s1.substring(0,d);    // 多处部分字符串              
    			whd += ((double)Long.parseLong(ps1, 2)*exp3);  // 加上多出部分的海明距离
    			
    			/**
    			 * 计算对齐部分的海明距离
    			 */
    			String left1 = s1.substring(d);   // 剩余字符串
    			String ps2 = s2.substring(0, len2+e2);
    			int leftlen1 = left1.length();
    			
    			/* 将字符串转化为字符数组     */
    			char[] c1 = left1.toCharArray();
    			char[] c2 = ps2.toCharArray();
    			
    			/* 构造异或字符串，结合幂，计算出对齐部分的海明距离   */
				char[] c = c2.clone();
				for(int i=0,size=c1.length;i<size;i++)
				{
					c[i]= (char)(c1[i]^c2[i]-48);
				}
				String  xorStr = new String(c);  // 异或字符串
				whd += ((double)Long.parseLong(xorStr, 2));  // 加上对齐部分的海明距离
    		}
    		else if(d<=len1 && e1<0 && e2>=0) //第一个浮点数的整数部分包含s1的子串 h0b1b2...b(len1+e1-1)，第二个浮点数的整数部分包含s2
    		{
    			/**
    			 *  计算多出部分的海明距离
    			 */
    			String ps1 = s1.substring(0,d);
    			whd += ((double)Long.parseLong(ps1, 2)*exp3);  // 加上多出部分的海明距离
    			
    			/**
    			 *  计算对齐部分的海明距离
    			 */
    			String left1 = s1.substring(d,len1+e1);
    			int leftlen1 = left1.length();
    			/* 将字符串转化为字符数组     */
    			char[] c1 = left1.toCharArray();
    			char[] c2 = s2.toCharArray();
    			
    			/* 构造异或字符串，结合幂，计算出对齐部分的海明距离   */
				char[] c = c1.clone();
				for(int i=0,size=c2.length;i<size;i++)
				{
					c[i]= (char)(c1[i]^c2[i]-48);
				}
				String  xorStr = new String(c);  // 异或字符串
				whd += ((double)Long.parseLong(xorStr, 2));  // 加上对齐部分的海明距离
    		}
    		else if(d<=len1 && e1<0 && e2<0) //第一个浮点数的整数部分包含s1的子串 h0b1b2...b(len1+e1-1)，第二个浮点数的整数部分包含s2的子串 H0B1B2...B(len2+e2-1)
    		{
    			// 由于两个浮点数的整数部分的长度都小于64，故可直接计算加权海明距离
    			char[] c1 = s1.substring(0, len1+e1).toCharArray();
    			char[] c2 = s2.substring(0, len2+e2).toCharArray();
    			char[] c = c1.clone();
    			for(int i=d,size=c1.length;i<size;i++)
    			{
    				c[i] = (char)(c1[i]^c2[i-d]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2));
    		}
    		else if(d > len1 && e2>=0) // e1必>0
    		{
    			/**
    			 *  计算多出部分的海明距离   
    			 */
    			whd += ((double)Long.parseLong(s1, 2)*(1<<(d-len1))*exp3);  // 加上多出部分的海明距离
    			
    			/**
    			 *  计算对齐部分的海明距离
    			 */
    			whd += ((double)Long.parseLong(s2, 2)*exp2);  // 加上对齐部分的海明距离
    		}
    		else // d>len1 && e2<0
    		{
    			/**
    			 *  计算多出部分的海明距离   
    			 */
    			whd += ((double)Long.parseLong(s1, 2)*(1<<(d-len1))*exp3);  // 加上多出部分的海明距离
    			
    			/**
    			 *  计算对齐部分的海明距离
    			 */
    			String ps2 = s2.substring(0, len2+e2);
    			whd += ((double)Long.parseLong(ps2, 2));  // 加上对齐部分的海明距离
    		}
    	} //if(len1+e1 > len2+e2)
    	else if(len1+e1 == len2+e2)  // 没有多出部分
    	{
    		/**
    		 *  计算对齐部分的海明距离
    		 */
    		if(len1 >= len2 && e1>=0 && e2>=0) // 第一个浮点数的整数部分包含s1，第二个浮点数的整数部分包含s2
    		{
    			char[] c1 = s1.toCharArray();
    			char[] c2 = s2.toCharArray();
    			char[] c =c1.clone();
    			for(int i=0,size=c2.length;i<size;i++)
    			{
    				c[i]=(char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2)*exp1);  // 加上对齐部分的海明距离
    		}
//    		else if(len1 >= len2 && e1>=0 && e2<0) //空集
    		else if(len1 >= len2 && e1<0 && e2>=0) //第一个浮点数的整数部分包含s1的子串 h0b1b2...b(len1+e1-1)，第二个浮点数的整数部分包含s2
    		{
    			// 由于两个浮点数的整数部分的长度都小于64，故可直接计算加权海明距离
    			char[] c1 = s1.substring(0, len1+e1).toCharArray();
    			char[] c2 = s2.toCharArray();
    			char[] c = c1.clone();
    			for(int i=0,size=c2.length;i<size;i++)
    			{
    				c[i] = (char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2));
    		}
    		else if(len1 >= len2 && e1<0 && e2<0) //第一个浮点数的整数部分包含s1的子串 h0b1b2...b(len1+e1-1)，第二个浮点数的整数部分包含s2的子串 H0B1B2...B(len2+e2-1)
    		{
    			// 由于两个浮点数的整数部分的长度都小于64，故可直接计算加权海明距离
    			char[] c1 = s1.substring(0, len1+e1).toCharArray();
    			char[] c2 = s2.substring(0, len2+e2).toCharArray();
    			char[] c = c1.clone();
    			for(int i=0,size=c1.length;i<size;i++)
    			{
    				c[i] = (char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2));
    		}
    		else if(len1<len2 && e1>=0 && e2>=0)
    		{
    			char[] c1 = s1.toCharArray();
    			char[] c2 = s2.toCharArray();
    			char[] c =c2.clone();
    			for(int i=0,size=c1.length;i<size;i++)
    			{
    				c[i]=(char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2)*exp2);  // 加上对齐部分的海明距离
    		}
//    		else if(len1<len2 && e1<0 && e2>=0) // 空集
    		else if(len1<len2 && e1>=0 && e2<0)
    		{
    			// 由于两个浮点数的整数部分的长度都小于64，故可直接计算加权海明距离
    			char[] c1 = s1.toCharArray();
    			char[] c2 = s2.substring(0, len2+e2).toCharArray();
    			char[] c = c2.clone();
    			for(int i=0,size=c1.length;i<size;i++)
    			{
    				c[i] = (char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2));
    		}
    		else // len1<len2 && e1<0 && e2<0
    		{
    			// 由于两个浮点数的整数部分的长度都小于64，故可直接计算加权海明距离
    			char[] c1 = s1.substring(0, len1+e1).toCharArray();
    			char[] c2 = s2.substring(0, len2+e2).toCharArray();
    			char[] c = c1.clone();
    			for(int i=0,size=c1.length;i<size;i++)
    			{
    				c[i] = (char)(c1[i]^c2[i]-48);
    			}
    			String xorStr = new String(c);
    			whd += ((double)Long.parseLong(xorStr, 2));
    		}
    	}// else if(len1+e1 == len2+e2)
    	else // (len1+e1 < len2+e2)
    	{
    		return calBinaryWHD(s2, e2, s1, e1);
    	} 
    	return whd;
    }
    
    /**
     * 计算两个表示浮点数的二进制串的小数部分之间的加权海明距离
     * 第一个小数为 s1*2^(s1.length-1-y1), 第二个小数为 s2*2^(s2.length-1-y2), 
     * 这里s1、s2必须只由0或1组成，长度均不大于53且模4余1
     * @param s1: ="h0b1b2b3...b(4*k1)" , h0,bi (1<=i<=4*k1)为字符0或1 
     * @param y1: 
     * @param s2: ="H0B1B2B3...B(4*k2)" , H0,Bj (1<=j<=4*k2)为字符0或1
     * @param y2: 
     * @return
     */
    private static double calPoinBinaryWHD(String s1,int y1,String s2,int y2)
    {
    	double whd = 0.0;
    	int len1 = s1.length(); // len1%4 =1
    	int len2 = s2.length();
    	int minus1 = len1-1-y1;
    	int minus2 = len2-1-y2;
    	double exp1 = Math.pow(2, -minus1);
    	double exp2 = Math.pow(2, -minus2);
    	
    	/**
    	 *  小数部分均为0   
    	 */  
    	if(minus1<=0 && minus2<=0)
    	{
    		return 0;
    	}
    	
    	/**
    	 *  一个浮点数的小数部分为0，另一个不为0
    	 */
    	else if(minus1>0 && minus2<=0)
    	{
    		if(0<=y1 && y1<len1-1)  // 此时 第一个浮点数为 h0b1b2...by1 . b(y1+1)b(y1+2)...b(4*k1), 小数部分为  0.b(y1+1)b(y1+2)...b(4*k1)
    		{
    			String ps1 = s1.substring(y1+1);
    			return (double)Long.parseLong(ps1, 2)*exp1;
    		}
    		else // y1<0, 此时 第一个浮点数为 0.h0b1b2...b(4*k1)  * 2^(y1+1), 小数部分为 0.00...0h0b1b2...b(4*k1)  ,小数点和h0之间共 -(y1+1)个0
    		{
    			return (double)Long.parseLong(s1, 2)*exp2;
    		}
    	}
    	
    	else if(minus1<=0 && minus2>0)
    	{
    		if(0<=y2 && y2<len2-1)  // 此时 第二个浮点数为 H0B1B2...By2 . B(y2+1)B(y2+2)...B(4*k2), 小数部分为  0.B(y2+1)B(y2+2)...B(4*k2)
    		{
    			String ps2 = s2.substring(y2+1);
    			return (double)Long.parseLong(ps2, 2)*exp2;
    		}
    		else // y2<0, 此时 第二个浮点数为 0.H0B1B2...B(4*k2)  * 2^(y2+1), 小数部分为 0.00...0H0B1B2...B(4*k2)  ,小数点和B0之间共 -(y2+1)个0
    		{
    			return (double)Long.parseLong(s2, 2)*exp2;
    		}
    	}
    	
    	/**
    	 *  小数部分均不为0, 先将小数部分对齐，计算长串多出部分的加权海明距离，再计算对齐部分的海明距离，二者相加得最终结果
    	 */
    	else  //  	(len1-1-y1>0 && len2-1-y2>0)
    	{
    		if(minus1 > minus2)
    		{
    			
    			int d = minus1-minus2;   // 多出部分的长度
    			if(d >= len1) // 多出部分包含s1
    			{
    				/**
        			 *  计算多出部分的加权海明距离
        			 */
    				whd += (double)Long.parseLong(s1, 2)*exp1;   // 加上多出部分的海明距离
    				
    				/**
        			 *  计算对齐部分的加权海明距离
        			 */
    				if(minus2 >= len2)  // 第二个浮点数的小数部分包含s2
    				{
    					whd += (double)Long.parseLong(s2, 2)*exp2;   // 加上对齐部分的海明距离
    				}
    				else // 第二个浮点数的小数部分包含s2的子串， B(1+y2)B(2+y2)...B(4*k2)
    				{
    					String ps2 = s2.substring(1+y2);
    					whd += (double)Long.parseLong(ps2, 2)*exp2;   // 加上对齐部分的海明距离
    				}
        			
    			} //if(d >= len1)
    			else   // d<len1 多出部分包含s1的子串 b(4*k1-d+1)b(4*k1-d+2)...b(4*k1)
    			{
    				String ps1 = s1.substring(len1-d);
    				String left1 = s1.substring(0, len1-d);
    				
    				/**
        			 *  计算多出部分的加权海明距离
        			 */
    				whd += (double)Long.parseLong(ps1, 2)*exp1;   // 加上多出部分的海明距离
    				
    				/**
        			 *  计算对齐部分的加权海明距离
        			 */
    				if(minus1 >= len1 && minus2 >= len2) // 第一个浮点的小数部分包含s1, 第二个浮点数的小数部分包含s2
    				{
    					if(len1-d >= len2 )
        				{
        					char[] c1 = left1.toCharArray();
        					char[] c2 = s2.toCharArray();
        					char[] c = c1.clone();
        					
        					for(int i=len1-d-len2,offset=len1-d-len2,size=len1-d;i<size;i++)
        					{
        						c[i]=(char)(c1[i]^c2[i-offset]-48);
        					}
        					String xorStr = new String(c);
                			whd += (double)Long.parseLong(xorStr, 2)*exp2;  // 加上对齐部分的海明距离
        				}
        				else
        				{
        					char[] c1 = left1.toCharArray();
        					char[] c2 = s2.toCharArray();
        					char[] c = c2.clone();
        					
        					for(int i=len2-(len1-d),offset=len2-(len1-d);i<len2;i++)
        					{
        						c[i]=(char)(c1[i-offset]^c2[i]-48);
        					}
        					String xorStr = new String(c);
                			whd += (double)Long.parseLong(xorStr, 2)*exp2;  // 加上对齐部分的海明距离
        				}
    				}
    				else if(minus1 >= len1 && minus2 < len2) // 第一个浮点的小数部分包含s1, 第二个浮点数的小数部分包含s2的子串 B(1+y2)B(2+y2)...B(4*k2)
    				{
    					String ps2 = s2.substring(1+y2);
    					if(len1-d < len2)
    					{
    						char[] c1 = left1.toCharArray();
    						char[] c2 = ps2.toCharArray();
    						char[] c = c2.clone();
    						for(int i=c2.length-c1.length,offset=1+y1,size=c2.length;i<size;i++)  // c2.length-c1.length = len2-1-y2 - (len1-d) = -1-y1
    						{
    							c[i] = (char)(c1[i+offset]^c2[i]-48);
    						}
    						String xorStr = new String(c);
    						whd += (double)Long.parseLong(xorStr, 2)*exp2;  // 加上对齐部分的海明距离
    					}
    					// if( len1 -d >= len2) 为空集
    				}
    				else if(minus1 < len1 && minus2 >= len2) // 第一个浮点数的小数部分包含s1的子串 b(1+y1)b(2+y1)...b(4*k1), 第二个浮点的小数部分包含s2,
    				{
    					String pleft1 = left1.substring(1+y1);
    					if(len1-d >= len2)
    					{
    						char[] c1 = pleft1.toCharArray();
    						char[] c2 = s2.toCharArray();
    						char[] c = c1.clone();
    						for(int i=c1.length-c2.length,offset=1+y2,size=c1.length;i<c1.length;i++) // c1.length-c2.length = len1-d-(1+y1) - len2 = -1-y2
    						{
    							c[i] = (char)(c1[i]^c2[i+offset]-48);
    						}
    						String xorStr = new String(c);
    						whd += (double)Long.parseLong(xorStr, 2)*exp2;  // 加上对齐部分的海明距离
    					}
    					// if(len1-d < len2) 为空集
    				}
    				else // (len1-1-y1<len1 && len2-1-y2<len2)  第一个浮点数的小数部分包含s1的子串 b(1+y1)b(2+y1)...b(4*k1)，第二个浮点数的小数部分包含s2的子串 B(1+y2)B(2+y2)...B(4*k2)
    				{
    					String pleft1 = left1.substring(1+y1);
    					String ps2 = s2.substring(1+y2);
    					char[] c1 = pleft1.toCharArray();
    					char[] c2 = ps2.toCharArray();
    					char[] c = c1.clone();
    					for(int i=0,size=c.length;i<size;i++)
    					{
    						c[i] = (char)(c1[i]^c2[i]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp2;  // 加上对齐部分的海明距离
    				}
    			}
    			
    			
    		}// if(len1-1-y1 > len2-1-y2)
    		else if(minus1 == minus2)
    		{
    			
    			if(minus1 >= len1) // 小数部分包含s1
    			{
    				if(len1<=len2 && len2<= minus1) // 小数部分包含s2, s2长度大于等于s1
    				{
    					/**
    	    			 *  计算对齐部分的加权海明距离
    	    			 */
    					char[] c1 = s1.toCharArray();
    					char[] c2 = s2.toCharArray();
    					char[] c = c2.clone();
    					for(int i=len2-len1,offset=-(len2-len1);i<len2;i++)
    					{
    						c[i] = (char)(c1[i+offset]^c2[i]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp1; // 加上对齐部分的海明距离
    				}
    				else if(len2<len1)// 小数部分包含s2, s2长度小于s1
    				{
    					/**
    	    			 *  计算对齐部分的加权海明距离
    	    			 */
    					char[] c1 = s1.toCharArray();
    					char[] c2 = s2.toCharArray();
    					char[] c = c1.clone();
    					for(int i=len1-len2,offset=-(len1-len2);i<len1;i++)
    					{
    						c[i] = (char)(c1[i]^c2[i+offset]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp1; // 加上对齐部分的海明距离
    				}
    				else // len2 > len1-1-y1, 小数部分包含 s2的子串 BxB(x+1)...B(4*k2), x满足 4*k2-x+1 = len1-1-y1, 及 len2-x = len2-1-y2, 得x=1+y2
    				{
    					/**
    	    			 *  计算对齐部分的加权海明距离
    	    			 */
    					String ps2 = s2.substring(1+y2);
    					char[] c1 = s1.toCharArray();
    					char[] c2 = ps2.toCharArray();
    					char[] c = c2.clone();
    					for(int i=minus1-len1,offset=-(minus1-len1),size=c.length;i<size;i++)
    					{
    						c[i] = (char)(c1[i+offset]^c2[i]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp1; // 加上对齐部分的海明距离
    				}
    			} //if(len1-1-y1 >= len1)
    			else // len1 > len1-1-y1, 小数部分包含 s1的子串 bxb(x+1)...b(4*k1), x满足 4*k1-x+1 = len1-1-y1, 及 len1-x = len1-1-y1, 得x=1+y1
    			{
    				if(len2<=minus1)  // 小数部分包含 s2
    				{
    					/**
    	    			 *  计算对齐部分的加权海明距离
    	    			 */
    					String ps1 = s1.substring(1+y1);
    					char[] c1 = ps1.toCharArray();
    					char[] c2 = s2.toCharArray();
    					char[] c = c1.clone();
    					for(int i=minus1-len2,offset=-(minus1-len2),size=c.length;i<size;i++)
    					{
    						c[i] = (char)(c1[i]^c2[i+offset]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp1; // 加上对齐部分的海明距离
    				}
    				else// len2 > len1-1-y1, 小数部分包含 s2的子串 BxB(x+1)...B(4*k2), x满足 4*k2-x+1 = len1-1-y1, 及 len2-x = len2-1-y2, 得x=1+y2
    				{
    					/**
    	    			 *  计算对齐部分的加权海明距离
    	    			 */
    					String ps1 = s1.substring(1+y1);
    					String ps2 = s2.substring(1+y2);
    					char[] c1 = ps1.toCharArray();
    					char[] c2 = ps2.toCharArray();
    					char[] c = c2.clone();
    					for(int i=0,size=c.length;i<size;i++)
    					{
    						c[i] = (char)(c1[i]^c2[i]-48);
    					}
    					String xorStr = new String(c);
    					whd += (double)Long.parseLong(xorStr, 2)*exp1; // 加上对齐部分的海明距离
    				}
    			}
    		} //else if(len1-1-y1 == len2-1-y2)
    		else // len1-1-y1 < len2-1-y2
    		{
    			return calPoinBinaryWHD( s2,y2,s1,y1);
    		}
    	}
    	return whd;
    }
    
	/**
	 * 计算目标路径被覆盖到的最长部分路径
	 * @param excutedPaths
	 * @param targetPath
	 * @return
	 */
	private static CFGPath getCoveredPath(List<CFGPath> excutedPaths, CFGPath targetPath)
	{
		CFGPath coveredPath = new CFGPath();
		
		int size = excutedPaths.size();
		for (int i=0; i<size; i++)
		{
			CFGPath tempPath = excutedPaths.get(i).getCoveredPath(targetPath);
			if (tempPath.getPath().size() > coveredPath.getPath().size())
			{
				coveredPath = tempPath;
			}
		}
		
		return coveredPath;
	}
	
	/**
     * 当一个染色体表示多个参数时，将一个String类型的染色体转换为double类型的数组。
     * @param sChromosome
     * @return long[]
     */
    public static long[] getChromValAsArray(String sChromosome) {
    	long digit;

    	long[] parameters = new long[numOfParamsAndAuxiVars];
    	
    	for(int i = numOfParamsAndAuxiVars;i > 0;i--){
			for(int j = len * i-1;j>=len * (i-1);j--){
		            if (sChromosome.charAt(j) == '1')
		                digit = 1;
		            else
		                digit = 0;
		            parameters[i-1] += (digit << (len*i - j - 1));
		    }
    	}
        
        return parameters; 		
    }

    /**
	 * @param nodeName
	 * @param path
	 * @return
	 */
	private static boolean isNodeInPath(String nodeName,CFGPath path)
	{
		List<SimpleCFGNode> sno = path.getPath();
		List<String> snoNameList = new ArrayList<String>();
		for(int i=0,size=sno.size();i<size;i++)
		{
			snoNameList.add(sno.get(i).getName());
		}
		if(snoNameList.contains(nodeName))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}